/*
 * Clase que instancia los árboles los cuales contendrán el diseño
 * lógico elaborado por el usuario. Este será un árbol enario, esto
 * quiere decir que cada nodo puede tener una cantidad n de hijos sin
 * un orden específico.
 */
package estructuras;

import fuente.compuertas.CompuertasNEntradas;

/**
 * @author Alexandre
 * @author Rodrigo
 * @author Gabriel
 * @author Jeremy
 */

public class ANB {
    
    private ANBNode _raiz; //Nodo raiz del arbol.
    
    
    /**
     * Constructor, Inicializa el árbol con una referencia a su raíz.
     * @param pRoot Raiz del árbol
     */
    public ANB (ANBNode pRoot) {
        _raiz  = pRoot;
    }

    
    ////Getters y setters////
    /**
     * Obtiene el nodo raíz del árbol que representa
     * una salida del diseño lógico.
     * @return Raíz
     */
    public ANBNode getRaiz() {
        return _raiz;
    }

    /**
     * Establece el nodo raíz del árbol que representa
     * una salida del diseño lógico.
     * @param pRaiz Nueva raíz del árbol
     */
    public void setRaiz(ANBNode pRaiz) {
        this._raiz = pRaiz;
    }
    /////////////////////////////////////////////////////////
    
    /**
     * Establece los valores de las entradas del diseño lógico.
     * @param pRoot Raiz del árbol
     * @param pListaValores Lista de los valores para establecer
     */
    public void establecerValorEntradas(ANBNode pRoot, SLL pListaValores) {
        if (!pRoot.isComp()) {
            int entrada = Integer.parseInt(pRoot.getCompuertaGraf().substring(1));
            
            int conta = 1;
            while (conta != entrada) {
                conta ++;
            }
            pRoot.setValor((int) pListaValores.obtenerPorPosicion(conta));
        }
        
        else {
            for (SLLNode n = pRoot.getHijos().getHead(); n != null; n = n.getNext()){
                establecerValorEntradas((ANBNode) n.getElemento(), pListaValores);
            }
        }
    }
    
    /**
     * Obtiene el valor de salida definitivo de un diseño de compuertas
     * lógicas, esto es, el valor del árbol comenzando a extraer valores
     * de forma recursiva empezando por la raíz del mismo y recorriendo
     * cada compuerta (Nodo) del árbol.
     * @param pRoot Raíz del árbol para evaluar salida
     * @return valor de salida binario definitivo
     */
    public int obtenerSalida(ANBNode pRoot) {
        SLL listaEntradas = new SLL();
        if (!pRoot.isComp()) {
            return pRoot.getValor();
        }
        
        else {
            for (SLLNode n = pRoot.getHijos().getHead(); n != null; n = n.getNext()) {
                listaEntradas.meterFinal(obtenerSalida((ANBNode)n.getElemento()));
            }
            switch (pRoot.getCompuertaName()) {
                case "AND":
                    return CompuertasNEntradas.salidaAND(listaEntradas);
                case "OR":
                    return CompuertasNEntradas.salidaOR(listaEntradas);
                case "NAND":
                    return CompuertasNEntradas.salidaNAND(listaEntradas);
                case "NOR":
                    return CompuertasNEntradas.salidaNOR(listaEntradas);
                case "XOR":
                    return CompuertasNEntradas.salidaXOR(listaEntradas);
                case "XNOR":
                    return CompuertasNEntradas.salidaXNOR(listaEntradas);
                default:
                    return CompuertasNEntradas.salidaNOT((int)listaEntradas.getHead().getElemento());
            }
        }
    }
    
    public void insertarEntrada (ANBNode pEntrada) {
        
    }
}

